import logging
import datetime
from sqlalchemy import func
from flask_restplus import Resource, Namespace, fields, marshal_with
from sqlalchemy.orm import load_only
from sqlalchemy import extract, and_
from sqlalchemy.sql.functions import count, sum

from common.utils.decorators import login_required
from flask import g, request, jsonify, Response
from app.models import db
from app import redis_clent, app
from flask_restplus import reqparse, inputs
from app.tasks.test import test
from app.routes.home_data.schemas import HomeSchemas
from .marshmallow import (
    UserRegistrationQuerySerializer,
    UserRegistrationBodySerializer,
    UserInfoQuerySerializer,
    UserBodySerializer,
    UserDataSerizlizer,
    UserLoginQuerySerizlizer,
    UserTokenSerizlizer,
    UserListQuerySerializer,
    RoleBodyListSerializer,
    UserNumberSerializer,
    ImportFileQuerySerializer,
    CarDataCostQuerySerializer,
)
from ...models.car import CarInfo
from ...models.user import User, Role
from app.models.road_toll import RoadToll
from app.models.ruel_cost import RuelCost
from app.models.parking_rate import ParkingRate
from app.models.collection import DataCollection, ParkingCollection

LOG = logging.getLogger(__name__)

home_data_ns = Namespace("home_data")

home_mh = HomeSchemas(home_data_ns)


class CarDataCostView(Resource):
    @home_data_ns.doc(params=home_mh.car_data_cost_query())
    def get(self):
        """车辆数据"""
        # 获取车辆id列表
        response = CarDataCostQuerySerializer().load(data=request.args)

        return response


class ImportFileView(Resource):
    @home_data_ns.expect(home_mh.import_file_json())
    def post(self):
        """
        导入表格
        """
        serializer = ImportFileQuerySerializer()
        serializer.context["request"] = request

        response = serializer.load(data=request.form)

        return response

        pass


class CollentionDetailsView(Resource):
    def get(self, id):

        # 通过user_id查询用户数据
        try:
            user = User.query.get(id)
        except Exception as e:
            raise e
        x_data = ["日期", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
        y_mileage_data = ["采集里程"]
        y_file_size_data = ["文件大小"]
        y_file_num_data = ["文件数量"]

        for i in range(13):
            if i == 0:
                continue
            mileage_data = (
                db.session.query(DataCollection.user, sum(DataCollection.course).label("total"))
                .group_by(DataCollection.user)
                .filter(
                    DataCollection.user == user.id,
                    extract("year", RuelCost.create_time) == datetime.datetime.now().year,
                    extract("month", RuelCost.create_time) == i,
                )
                .first()
            )

            file_size_data = (
                db.session.query(DataCollection.user, sum(DataCollection.file_size).label("total"))
                .group_by(DataCollection.user)
                .filter(
                    DataCollection.user == user.id,
                    extract("year", RuelCost.create_time) == datetime.datetime.now().year,
                    extract("month", RuelCost.create_time) == i,
                )
                .first()
            )

            file_num_data = (
                db.session.query(DataCollection.user, sum(DataCollection.file_num).label("total"))
                .group_by(DataCollection.user)
                .filter(
                    DataCollection.user == user.id,
                    extract("year", RuelCost.create_time) == datetime.datetime.now().year,
                    extract("month", RuelCost.create_time) == i,
                )
                .first()
            )

            if not mileage_data:
                y_mileage_data.append(0)
            else:
                y_mileage_data.append(float(mileage_data.total))

            if not file_num_data:
                y_file_num_data.append(0)
            else:
                y_file_num_data.append(int(file_num_data.total))

            if not file_size_data:
                y_file_size_data.append(0)
            else:
                y_file_num_data.append(float(file_size_data.total))

        return jsonify({"data": [x_data, y_file_num_data, y_file_size_data, y_mileage_data]})


class CarDetailsView(Resource):
    def get(self, id):

        # 通过user_id查询用户数据
        try:
            user = User.query.get(id)
        except Exception as e:
            raise e
        x_data = ["日期", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
        y_road_data = ["过路费"]
        y_ruel_data = ["燃油费"]
        y_parking_data = ["停车费"]

        for i in range(13):
            if i == 0:
                continue
            ruel_data = (
                db.session.query(RuelCost.user, sum(RuelCost.total_price).label("total"))
                .group_by(RuelCost.user)
                .filter(
                    and_(
                        RuelCost.user == user.id,
                        extract("year", RuelCost.create_time) == datetime.datetime.now().year,
                        extract("month", RuelCost.create_time) == i,
                    )
                )
                .first()
            )
            parking_data = (
                db.session.query(ParkingRate.user, sum(ParkingRate.price).label("total"))
                .group_by(ParkingRate.user)
                .filter(
                    and_(
                        ParkingRate.user == user.id,
                        extract("year", ParkingRate.create_time) == datetime.datetime.now().year,
                        extract("month", ParkingRate.create_time) == i,
                    )
                )
                .first()
            )

            road_data = (
                db.session.query(RoadToll.user, sum(RoadToll.price).label("total"))
                .group_by(RoadToll.user)
                .filter(
                    and_(
                        RoadToll.user == user.id,
                        extract("year", RoadToll.create_time) == datetime.datetime.now().year,
                        extract("month", RoadToll.create_time) == i,
                    )
                )
                .first()
            )

            if not road_data:
                y_road_data.append(0)
            else:
                y_road_data.append(road_data.total)

            if not ruel_data:
                y_ruel_data.append(0)
            else:
                y_ruel_data.append(ruel_data.total)

            if not parking_data:
                y_parking_data.append(0)
            else:
                y_parking_data.append(parking_data.total)

        return {"data": [x_data, y_ruel_data, y_road_data, y_parking_data]}


class AssetDetailsView(Resource):
    @home_data_ns.marshal_with(home_mh.asset_user_body())
    def get(self):

        data = (
            db.session.query(Role.role_name, count(Role.users).label("count"))
            .group_by(Role.role_name)
            .filter(Role.id == User.role_id)
            .all()
        )
        user_num = UserNumberSerializer(many=True).dump(data)

        return user_num


class AssetCarNumView(Resource):
    @home_data_ns.marshal_with(home_mh.asset_car_body())
    def get(self):
        count = CarInfo.query.count()

        return {"count": count}


class UserTokenView(Resource):
    @home_data_ns.expect(home_mh.user_login_query(), validate=True)
    @home_data_ns.marshal_with(home_mh.user_token())
    def post(self):
        data = UserLoginQuerySerizlizer().load(data=request.json)
        response = UserTokenSerizlizer().dump(data)

        return response


class UserPutDeleteView(Resource):
    # method_decorators = {"get": [login_required]} # 检查用户登录的装饰器

    @home_data_ns.marshal_with(home_mh.user_info_body())
    def get(self, id):

        try:
            user = User.query.get(id)
        except Exception as e:
            raise e

        response = UserBodySerializer().dump(user)

        return response

    def delete(self, id):

        try:
            user = User.query.get(id)
        except Exception as e:
            raise e

        user.deleted = True
        db.session.commit()

        return Response(status=204 if user else 500)

    @home_data_ns.expect(home_mh.user_registr_query(), validate=False)
    def put(self, id):
        print(request.data)

        try:
            user = User.query.filter(User.id == id).update(request.json)
        except Exception as e:
            raise e

        return Response(status=202 if user else 500)


class UserLoginView(Resource):
    # method_decorators = {"get": [login_required]} # 检查用户登录的装饰器
    @home_data_ns.expect(home_mh.user_registr_query(), validate=False)
    @home_data_ns.marshal_with(home_mh.user_registr_body())
    def post(self):
        user = UserRegistrationQuerySerializer().load(data=request.json)
        response = UserRegistrationBodySerializer().dump(user)
        return response


class UserInfoView(Resource):
    # method_decorators = [login_required]

    @home_data_ns.doc(params=home_mh.user_list_query())
    @home_data_ns.marshal_with(home_mh.user_info_body())
    def get(self):

        user = UserInfoQuerySerializer().load(data={"id": g.user_id})
        response = UserBodySerializer().dump(user)

        return response


class UserListView(Resource):
    # method_decorators = [login_required]

    @home_data_ns.doc(params=home_mh.user_list_query())
    @home_data_ns.marshal_with(home_mh.user_list_body())
    def get(self):

        user, total = UserListQuerySerializer().load(data=request.args)
        response = UserDataSerizlizer().dump({"total": total, "data": user})

        return response


class UserRoleListView(Resource):
    # method_decorators = [login_required]

    @home_data_ns.marshal_with(home_mh.role_body())
    def get(self):

        roles = Role.query.filter().all()

        response = RoleBodyListSerializer(many=True).dump(roles)

        return response
